package com.deer.wms.ware.task.web;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deer.wms.intercept.annotation.User;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.core.result.Result;
import com.deer.wms.project.root.core.result.ResultGenerator;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.system.manage.model.dept.Dept;
import com.deer.wms.system.manage.model.user.UserInfo;
import com.deer.wms.system.manage.model.ware.WareInfo;
import com.deer.wms.system.manage.service.DeptService;
import com.deer.wms.system.manage.service.UserInfoService;
import com.deer.wms.ware.task.constant.WareTaskConstant;
import com.deer.wms.ware.task.model.SO.*;
import com.deer.wms.ware.task.model.Wave.*;
import com.deer.wms.ware.task.service.SoDetailService;
import com.deer.wms.ware.task.service.SoMasterService;
import com.deer.wms.ware.task.service.WaveDetailService;
import com.deer.wms.ware.task.service.WaveMasterService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

import static com.deer.wms.project.root.util.CollectionUtils.convertMap;
import static java.util.Collections.*;

/**
 *
 * @author ll
 * @since 2020/02/02
 */
@RestController
@RequestMapping("/wave/masters")
public class WaveMasterController {

    @Autowired
    private WaveMasterService waveMasterService;
    @Autowired
    WaveDetailService waveDetailService;
    @Autowired
    SoMasterService soMasterService;
    @Autowired
    private SoDetailService soDetailService;
    @Autowired
    private DeptService deptService;

    @PostMapping
    public Result add(@RequestBody WaveMaster waveMaster) {
        waveMasterService.save(waveMaster);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/delete")
    public Result delete(Integer id) {
        waveDetailService.deleteByWaveMasterId(id);
        waveMasterService.removeById(id);
        return ResultGenerator.genSuccessResult();
    }

    @Autowired
    private UserInfoService userInfoService;

    @PostMapping("/update")
    public Result update(@RequestBody WaveMaster waveMaster) {
        UserInfo userInfo = userInfoService.getById(waveMaster.getAllotUserId());
        waveMaster.setAllotUserName(userInfo.getUserName());
        waveMaster.setAllotTime(DateUtils.getNowDateTimeString());
        waveMasterService.updateById(waveMaster);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/{id}")
    public Result detail(@PathVariable Integer id) {
        WaveMaster waveMaster = waveMasterService.getById(id);
        return ResultGenerator.genSuccessResult(waveMaster);
    }

    @GetMapping("/list")
    public Result list(WaveMasterCriteria criteria,@ApiIgnore @User CurrentUser currentUser) {
        criteria.setAllotUserId(currentUser.getUserId());
        criteria.setIsAdmin(currentUser.getIsAdmin());
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        List<WaveMasterDto> list = waveMasterService.findList(criteria);
        // 去除复核完成和完全拆单的波次
//        list = list.stream().filter(item -> item.getState() < 3).collect(Collectors.toList());
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("/list/pick")
    public Result listForPick(WaveDetailCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        List<WaveDetail> detailList = waveDetailService.list(new QueryWrapper<WaveDetail>()
//                .in("state", Arrays.asList(1, 2))
                        .apply("allotted_quantity>pick_quantity")
                        .in(currentUser.getIsAdmin() != 1, "pick_user_id", currentUser.getUserId())

        );
        List<WaveDetail> collect = detailList.stream().filter(detail -> detail.getQuantity() > detail.getPickQuantity()).collect(Collectors.toList());
        List<WaveDetail> waveDetailDtos = collect.stream().filter(item -> item.getPickQuantity() < item.getAllottedQuantity()).collect(Collectors.toList());
        List<WaveMaster> waveMasterList = new ArrayList<>();
        if(waveDetailDtos.size()>0){
            Set<String> wacodes = waveDetailDtos.stream().map(WaveDetail::getWaveCode).collect(Collectors.toSet());
            QueryWrapper<WaveMaster> qw = new QueryWrapper<>();
            qw.in("code",wacodes);
            waveMasterList = waveMasterService.list(qw);
        }
        Set<Integer> deptIds = waveMasterList.stream().map(item -> item.getDeptId()).collect(Collectors.toSet());
        List<Dept> depts = deptService.listByIds(deptIds);
        Map<Integer, Dept> deptMap = convertMap(depts, Dept::getDeptId);
        for (WaveMaster waveMaster : waveMasterList) {
            Dept dept = deptMap.get(waveMaster.getDeptId());
            waveMaster.setDeptName(Optional.ofNullable(dept).map(item -> dept.getDeptName()).orElse(""));
        }
//        PageInfo pageInfo = new PageInfo(waveMasterList);
        return ResultGenerator.genSuccessResult(waveMasterList);
    }

    @GetMapping("/allotWave")
    public Result allotWave(WaveMasterCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        criteria.setUserId(currentUser.getUserId());
        List<WaveMasterDto> list = waveMasterService.allotWave(criteria);
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("/generateWaves")
    public Result generateWaves() {
        waveMasterService.generateWaves();
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/transToWave")
    public Result transToWave(@RequestBody WaveDetailTransData waveDetailTransData) {
        WaveMaster wave = waveMasterService.getById(waveDetailTransData.getWaveId());
        for (Integer waveDetailId : waveDetailTransData.getWaveDetailIds()) {
            WaveDetail waveDetail = waveDetailService.getById(waveDetailId);
            waveDetail.setWaveMasterId(wave.getWaveId());
            waveDetailService.updateById(waveDetail);
        }
        return ResultGenerator.genSuccessResult();
    }


    @GetMapping("onSoMaster")
    public Result onSoMaster(String waveCode,String itemCode) {

       List<SoDetail> list =  waveMasterService.onSoMaster(waveCode, itemCode);
        return ResultGenerator.genSuccessResult(list);
    }







    @GetMapping("/allotPickUser")
    public Result allotPickUser(Integer waveMasterId, Integer userId, String userName) {

        WaveMaster wave = waveMasterService.getById(waveMasterId);
        wave.setAllotTime(DateUtils.getNowDateTimeString());
        wave.setAllotUserId(userId);
        wave.setAllotUserName(userName);
        waveMasterService.updateById(wave);
        return ResultGenerator.genSuccessResult();
    }

//    @GetMapping("/listForPda")
//    public Result listForPda() {
//        List<WaveMasterDto> list = new ArrayList<>();
//        WaveMasterCriteria criteria = new WaveMasterCriteria();
//        criteria.setState(WareTaskConstant.WAVE_STATE_PICKING);
//        list.addAll(waveMasterService.findList(criteria));
//        criteria.setState();
//        PageInfo pageInfo = new PageInfo(list);
//        return ResultGenerator.genSuccessResult(pageInfo);
//    }





    @ApiOperation(value = "合并SO", notes = "生成波次（配料单）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    @PostMapping("/merge")
    public Result merge(@RequestBody Merge merge, @ApiIgnore @User CurrentUser currentUser) {

        List<SoMaster> soMasters = soMasterService
                .list(new QueryWrapper<SoMaster>().in("bill_no", merge.getBillNos()));
        waveMasterService.robAndStart(merge.getBillNos());

        //校验SO的状态，只允许初始化的单据能生成波次
        for (SoMaster soMaster : soMasters) {
            if (ObjectUtil.notEqual(soMaster.getState(), WareTaskConstant.SO_STATE_INIT)) {
                if(ObjectUtil.equal(soMaster.getState(), 1)){//增加拆单状态可以再次合并
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "只允许新建(拆单)状态的出库任务进行合并，请确认单据【" + soMaster.getBillNo() + "】");
                }
            }
        }
        //判断是否是同一部门和同一任务单号
        Map<Integer, List<SoMaster>> soMap = soMasters.stream().collect(Collectors.groupingBy(SoMaster::getDeptId));
        //部门id排序
        List<Integer> ids =new ArrayList<>(soMap.keySet());
        //部门校验
        if (ids.size() > 1) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "存在多个部门的任务，不允许合并");
        }
//        switchDept(ids);
        //查询任务单明细
        List<SoDetail> soDetailList  = soDetailService.list(new QueryWrapper<SoDetail>().in("bill_no", merge.getBillNos()));
        List<SoDetail> filterSoDetail = soDetailList.stream().filter(item -> item.getAllottedQuantity() < item.getOrderQuantity()).collect(Collectors.toList());
        waveMasterService.mergeSo(soMasters, currentUser, filterSoDetail, merge.getRemake());
        return ResultGenerator.genSuccessResult();
    }


    public boolean switchDept(List<Integer> ids) {
//        List<Integer> switchDept = Arrays.asList(107, 349805);
//        sort(ids);
//        if (switchDept.equals(ids) ) {
//            return true;
//        }
        if (ids.size() > 1) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "存在多个部门的任务，不允许合并");
        } else {
            return true;
        }
    }


    @ApiOperation(value = "波次拆分", notes = "波次拆分")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    @GetMapping("/split/{waveCode}")
    public Result split(@PathVariable String  waveCode, @ApiIgnore @User CurrentUser currentUser) {
        waveMasterService.split(waveCode);
        return ResultGenerator.genSuccessResult();
    }


}